home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / text / font / ttf2pfb.lha / ttf2pfb.c < prev    next >
C/C++ Source or Header  |  1998-07-11  |  39KB  |  1,294 lines

  1. /*
  2.  *  ttf2pfb.c -- TrueType to PostScript Type 1 Font converter.
  3.  * 
  4.  * Author: Chun-Yu Lee <d791013@ce.ntu.edu.tw>
  5.  *
  6.  * The generated output is in a raw Type 1 Font format, required
  7.  * encoders (e.g. t1asm or t1binary) converting to PFA or PFB font.
  8.  *
  9.  * This program was adapted from the ntu2cjk package (part of the
  10.  * LaTeX2e CJK package (by Werner Lemberg <wl@gnu.org>))
  11.  * and those of contributed and test programs in the FreeType archive
  12.  * tree.
  13.  */
  14.  
  15. /*
  16.  * Requirement:
  17.  *   - the FreeType (v1.0, maybe higher) Library.
  18.  *   - T1asm or similar converter if PFA or PFB format required
  19.  *   - getafm or similar one if AFM font metrics required.
  20.  *   - afm2tfm or similar one if TFM form metrics required.
  21.  *   - CJK package (including the ntu2cjk part) if typesetting LaTeX
  22.  *     documents using the generated fonts.
  23.  *   - dvips 5.66 or higher if self-contained PostScript document
  24.  *     outputs are required. 
  25.  *   - Ghostscript 3.33 or higher to be complement of some packages
  26.  *     listed above.
  27.  */ 
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <stdarg.h>
  32. #include <string.h>
  33. #include <unistd.h>
  34. #include <ctype.h>
  35.  
  36. #include "freetype.h"
  37.  
  38. #ifndef lint
  39. char rcsid[] = "$Id: ttf2pfb.c,v 1.6 1998/07/11 06:05:12 werner Exp $";
  40. #endif
  41.  
  42. #ifndef TTF2PFB_VERSION
  43. #define TTF2PFB_VERSION "alpha"
  44. #endif
  45.  
  46. /* Set default values */
  47. #ifndef DEFAULT_PLATFORM_ID
  48. #define DEFAULT_PLATFORM_ID 3   /* for MS platform */
  49. #endif
  50.  
  51. #ifndef DEFAULT_ENCODING_ID
  52. #define DEFAULT_ENCODING_ID 4   /* for Big-5 encoding (ideally) */
  53. /* #define DEFAULT_ENCODING_ID 1 */   /* for Unicode encoding */
  54. #endif
  55.  
  56. #define PID_UNICODE 3
  57. #define EID_UNICODE 1
  58. #define PID_SJIS    3
  59. #define EID_SJIS    2
  60. #define PID_GB      3
  61. #define EID_GB      3
  62. #define PID_BIG5    3
  63. #define EID_BIG5    4
  64. #if 0
  65. #define PID_KS      3  /* ???? */
  66. #define EID_KS      5  /* ???? */
  67. #endif
  68.  
  69. /* The possible values for the `force_enc' variable. */
  70. typedef enum _enc_type
  71. {
  72.   GB = 1, JIS, KS, SJIS, X
  73. } enc_type;
  74.  
  75. /* A variable to enforce a certain font encoding (if > 0). */
  76. enc_type force_enc = 0;
  77.  
  78. #ifndef TRUE
  79. #define TRUE    1
  80. #define FALSE   0
  81. #define FAILURE -1
  82. #endif
  83.  
  84. #define LINELEN 40  /* max # of columns of code range file */
  85.  
  86. /*
  87.  * Flags and globals
  88.  */ 
  89. int     verbose   = FALSE;  /* messages should be printed or not. */
  90. int     compact   = FALSE;  /* generate compact font? */
  91. float   fontShift = 0; 
  92. /* float   fontShift = -0.15; */ /* shift down each char 15 percent of bbox */
  93.  
  94. #ifndef UShort
  95. typedef unsigned short UShort;
  96. #endif
  97. #ifndef UChar
  98. typedef unsigned char  UChar;
  99. #endif
  100.  
  101. #define TT_Flag_On_Curve 1
  102.  
  103. /* default platform and encoding ID's. */
  104. int     pid = DEFAULT_PLATFORM_ID;
  105. int     eid = DEFAULT_ENCODING_ID;
  106.  
  107. char*   prog;             /* program name */
  108.  
  109. /* for orthogonality with fprintf */
  110. #define Fputs(_string_) fprintf(out, "%s\n", _string_)
  111.  
  112. /* Postscript font related defines and functions */
  113. TT_F26Dot6 lastpsx, lastpsy;
  114.  
  115. #define Coord(x) (int)(x)
  116. #define PS_LastPt(x,y)  lastpsx = x; lastpsy = y
  117. #define PS_Moveto(x,y)  \
  118.         fprintf(out, "%d %d rmoveto\n", \
  119.                 Coord(x-lastpsx),Coord(y-lastpsy)); \
  120.         PS_LastPt(x,y)
  121. #define PS_Lineto(x,y)  \
  122.         fprintf(out, "%d %d rlineto\n", \
  123.                 Coord(x-lastpsx),Coord(y-lastpsy)); \
  124.         PS_LastPt(x,y)
  125.  
  126. /*
  127.  *  Freetype globals.
  128.  */
  129.  
  130. TT_Engine   engine;
  131. TT_Face     face;
  132. TT_Instance instance;
  133. TT_Glyph    glyph;
  134. TT_CharMap  cmap;
  135. TT_Error    error;
  136.  
  137. TT_Outline          outline;
  138. TT_Glyph_Metrics    metrics;
  139. TT_Face_Properties  properties;
  140. /* TT_BBox             bbox; */
  141.  
  142. /* 
  143.  *  Data structures defined for encoding vector
  144.  */
  145.  
  146. /* A code range file for the encoding vector of a font contains code
  147.    range pairs, each pair a line. Code starting and ending are seperated
  148.    by ' - ', note that the spaces before and after the minus sign are
  149.    significant. Several types of syntax are shown as follows:
  150.  
  151.    (Note that declared code ranges must be appeared in ascending order.)
  152.  
  153.    1. Absolute range, i.e. code is two byte number, e.g.:
  154.  
  155.       0xA140 - 0xA17E
  156.       41280  - 41342
  157.       0xE00000 - 0xE000FF
  158.  
  159.    The first two lines represent the same range. 
  160.  
  161.    2. Relative range, i.e. code is one byte number. If the line is ended
  162.    with a colon ':', it is designated the high byte(s) range, otherwise the
  163.    low byte range (only the last one byte). If there is no high byte(s)
  164.    range declared before the low byte range, the lastest defined high
  165.    byte(s) range or '0x00 - 0x00:' will be used. e.g.:
  166.  
  167.       0xA1 - 0xFE:
  168.         0x40 - 0x7E
  169.         0xA1 - 0xFE
  170.  
  171.    which is the Big-5 Encoding.
  172.  
  173.    3. Single code. Similar to absolute or relative range but the second
  174.    number of the range is the same as the first number. E.g.:
  175.  
  176.       0xA141  ==  0xA141 - 0xA141
  177.       0xA1:   ==  0xA1 - 0xA1:
  178.       0xA1    ==  0xA1 - 0xA1
  179.  
  180.    4. If the high byte range is declared and there is no low byte range
  181.    declared consecutively, it is assumed the low byte range is '0x00 - 0xFF'.
  182.  
  183.    5. Comment line. A hash mark '#' followed by any stuffs to the end of the
  184.    line is ignored. Blank line is also discarded.
  185.  
  186.    */
  187.  
  188. typedef struct _EVHigh
  189. {
  190.   UShort  start, end;
  191. } EVHigh;
  192.  
  193. typedef struct _EVLow 
  194. {
  195.   UChar  start, end;
  196. } EVLow;
  197.  
  198. typedef struct _EVcRange 
  199. {
  200.   EVHigh  high;
  201.   UShort  numLowRanges;
  202.   EVLow*  low;
  203. } EVcRange;
  204.  
  205. typedef struct _EncVec 
  206. {
  207.   UShort     numCodeRanges;
  208.   EVcRange*  codeRange;
  209. } EncVec;
  210.  
  211. /* Select encoding vector with respect to pid and eid */
  212. EncVec* eVecMap[5][10];
  213.  
  214. /* Select encoding vector with respect to force_enc */
  215. EncVec* eVecMap_force[10];
  216.  
  217. /*
  218.   Functions
  219. */
  220.  
  221. void
  222. mesg (const char *msg, ...) 
  223. {
  224.   va_list ap;
  225.   va_start (ap, msg);
  226.   vfprintf (stderr, msg, ap);
  227.   va_end (ap);
  228. }
  229.  
  230. /*
  231.  * Usage
  232.  */   
  233. void
  234. Usage (int eval)
  235. {
  236. #ifdef DEBUG
  237.   mesg ("Usage: %s [-h][-v][-c][-d charcode][-l][-ng][-nc]\n", prog);
  238. #else
  239.   mesg ("Usage: %s [-h][-v][-c]\n", prog);
  240. #endif
  241.   mesg ("\t[-pid id] [-eid id] [-force enc] [-enc file]\n");
  242.   mesg ("\t[-plane pl] [-f fname] [-uid id] [-s shift]\n");
  243.   mesg ("\t[-o output] [-ttf font.ttf | font.ttf]\n");
  244.   mesg ("-h\t\tThis message.\n");
  245.   mesg ("-v\t\tPrint messages during conversion.\n");
  246.   mesg ("-c\t\tCompact font, ie 256 chars a font");
  247.   mesg (" (useful for the CJK package).\n");
  248. #ifdef DEBUG
  249.   mesg ("-d charcode\tDebug CharString for the given character code.\n");
  250.   mesg ("-l\t\tDisplay point labels.\n");
  251.   mesg ("-ng\t\tDo not show glyph outline.\n");
  252.   mesg ("-nc\t\tDo not show control paths.\n");
  253. #endif
  254.   mesg ("-pid id\t\tSet the platform ID [%d].\n", DEFAULT_PLATFORM_ID);
  255.   mesg ("-eid id\t\tSet the encoding ID [%d].\n", DEFAULT_ENCODING_ID);
  256.   mesg ("\t\t(use a strange pid & eid pair to list all possible pid,eid)\n");
  257.   mesg ("-force enc\tForce a certain encoding [none].\n");
  258.   mesg ("\t\tpossible values are GB, JIS, KS, SJIS, and X).\n");
  259.   mesg ("-enc file\tFile contains code ranges [none].\n");
  260.   mesg ("-plane pl\tA single font plane [0x0].\n");
  261.   mesg ("-f fname\tFont name [UNKNOWN].\n");
  262.   mesg ("-uid id\t\tThe first four digits of UID of Type1 font [7000].\n");
  263.   mesg ("-s shift\tY-offset factor [%5.3f].\n", fontShift);
  264.   mesg ("-o outfile\tSet the output filename [stdout].\n");
  265.   mesg ("-ttf ttfpath\tThe TTF font pathname.\n");
  266.  
  267.   exit(eval);
  268. }
  269.  
  270. void
  271. fatal (const char *msg, ...) 
  272. {
  273.   va_list ap;
  274.   va_start (ap, msg);
  275.   fprintf (stderr, "%s: ", prog);
  276.   vfprintf (stderr, msg, ap);
  277.   fprintf (stderr, "\n");
  278.   va_end (ap);
  279.   exit (FAILURE);
  280. }
  281.  
  282. void
  283. fatal_error (const char *msg, ...) 
  284. {
  285.   va_list ap;
  286.   va_start (ap, msg);
  287.   fprintf (stderr, "%s: error code 0x%04lx: ", prog, error);
  288.   vfprintf (stderr, msg, ap);
  289.   fprintf (stderr, "\n");
  290.   va_end (ap);
  291.   exit (FAILURE);
  292. }
  293.  
  294. /*
  295.  * Realloc a pointer.
  296.  */
  297. void *
  298. re_alloc (void* ptr, size_t size, char* sub)
  299. {
  300.   register void* value = realloc (ptr, size);
  301.   if (value == NULL)
  302.     fatal ("%s: Virtual memory exhausted.\n", sub);
  303.   return value;
  304. }
  305.  
  306. /* We have to introduce the `dummy' integer to assure correct handling of
  307.    the stack.  Using `UShort' as the first parameter may fail in case
  308.    this type is promoted to a different type (as happens e.g. under
  309.    emx for DOS */
  310. EncVec* 
  311. Alloc_EncVec (int dummy, ...)
  312. {
  313.   va_list    vp;
  314.   EncVec*    encVec = NULL;
  315.   EVcRange*  cRange = NULL;
  316.   EVLow*     evLow  = NULL;
  317.   UShort     numCR, numLows;
  318.   int        i,j;
  319.  
  320.   va_start (vp, dummy);
  321.   numCR = va_arg (vp, UShort);
  322.  
  323.   encVec = re_alloc (encVec, 1*sizeof(EncVec), "Alloc_EncVec");
  324.   encVec->numCodeRanges = numCR;
  325.  
  326.   cRange = re_alloc (cRange, numCR*sizeof(EVcRange), "Alloc_EncVec");
  327.   for (i=0; i<numCR; i++) {
  328.     (cRange+i)->high.start   = va_arg (vp, UShort);
  329.     (cRange+i)->high.end     = va_arg (vp, UShort);
  330.     (cRange+i)->numLowRanges = numLows = va_arg (vp, UShort);
  331.     evLow = NULL;
  332.     evLow = re_alloc (evLow, numLows*sizeof(EVLow), "Alloc_EncVec");
  333.     for (j=0; j<numLows; j++) {
  334.       (evLow+j)->start = va_arg (vp, UChar);
  335.       (evLow+j)->end   = va_arg (vp, UChar);
  336.     }
  337.     (cRange+i)->low          = evLow;
  338.   }
  339.   encVec->codeRange     = cRange;
  340.  
  341.   va_end (vp);
  342.   return encVec;
  343. }
  344.   
  345. void
  346. Known_Encodings (void)
  347. {
  348.   EncVec*   encVec;
  349.  
  350.   /* Big-5 encoding */
  351.   encVec = Alloc_EncVec (1, 1, 0xA1, 0xFE, 2, 0x40, 0x7E, 0xA1, 0xFE);
  352.   eVecMap[PID_BIG5][EID_BIG5] = encVec;
  353.   /* eVecMap_force[BIG5] = encVec; */
  354.  
  355.   /* GB encoding */
  356.   encVec = Alloc_EncVec (2, 1, 0xA1, 0xF7, 1, 0xA1, 0xFE);
  357.   eVecMap[PID_GB][EID_GB] = encVec;
  358.   eVecMap_force[GB] = encVec;
  359.  
  360.   /* KS encoding */
  361.   encVec = Alloc_EncVec (3, 1, 0xA1, 0xFE, 1, 0xA1, 0xFE);
  362.   /* eVecMap[PID_KS][EID_KS] = encVec; */
  363.   eVecMap_force[KS] = encVec;
  364.  
  365.   /* JIS encoding */
  366.   encVec = Alloc_EncVec (4, 1, 0xA1, 0xF4, 1, 0xA1, 0xFE);
  367.   /* eVecMap[PID_JIS][EID_JIS] = encVec; */
  368.   eVecMap_force[JIS] = encVec;
  369.   eVecMap_force[X] = encVec;     /* will be internally translated to SJIS */
  370.  
  371.   /* Unicode encoding */
  372.   encVec = Alloc_EncVec (5, 1, 0x00, 0xFF, 1, 0x00, 0xFF);
  373.   eVecMap[PID_UNICODE][EID_UNICODE] = encVec;
  374.   /* eVecMap_force[UNICODE] = encVec; */
  375.  
  376.   /* SJIS encoding */
  377.   encVec = Alloc_EncVec (6, 3,  0x0,  0x0, 1, 0xA1, 0xDF,
  378.                             0x81, 0x9F, 2, 0x40, 0x7E, 0x80, 0xFC,
  379.                             0xE0, 0xEF, 2, 0x40, 0x7E, 0x80, 0xFC);
  380.   eVecMap[PID_SJIS][EID_SJIS] = encVec;
  381.   eVecMap_force[SJIS] = encVec;
  382. }
  383.  
  384. /*
  385.  *  Convert JIS to SJIS encoding.
  386.  */
  387. UShort
  388. JIS_to_SJIS (UShort code)
  389. {
  390.   UShort index;
  391.   UShort cc0 = (code >> 8) & 0xFF;
  392.   UShort cc1 = code & 0xFF;
  393.  
  394.   index = (cc0 - 0xa1) * (0xfe - 0xa1 + 1) + (cc1 - 0xa1);
  395.   cc0 = index / ((0x7e - 0x40 + 1) + (0xfc - 0x80 + 1));
  396.   cc1 = index % ((0x7e - 0x40 + 1) + (0xfc - 0x80 + 1));
  397.   if (cc0 < (0x9f - 0x81 + 1))
  398.     cc0 += 0x81;
  399.   else
  400.     cc0 += 0xe0 - (0x9f - 0x81 + 1);
  401.   if (cc1 < (0x7e - 0x40 + 1))
  402.     cc1 += 0x40;
  403.   else
  404.     cc1 += 0x80 - (0x7E - 0x40 + 1);
  405.  
  406.   return (cc0 << 8) + cc1;
  407. }
  408.  
  409. /*
  410.  * Open TTF file and select cmap
  411.  */
  412. int
  413. Init_Font_Engine (char* infile)
  414. {
  415.   short cmapindex, platformID, encodingID, num_cmap;
  416.  
  417.   error = TT_Init_FreeType (&engine);
  418.   if (error) 
  419.     fatal_error ("couldn't initialize FreeType engine.");
  420.                                 /* Open the input file. */
  421.   error = TT_Open_Face (engine, infile, &face);
  422.   if (error) fatal_error ("unable to open input file '%s'", infile);
  423.   /* Load the instance. */
  424.   error = TT_New_Instance (face, &instance);
  425.   if (error) fatal_error ("couldn't create instance.");
  426.  
  427.   error = TT_Set_Instance_Resolutions (instance, 600, 600);
  428.   if (error) fatal_error ("error setting resoluations.");
  429.   error = TT_Set_Instance_CharSize (instance, 120*64);
  430.   if (error) fatal_error ("error setting character size.");
  431.  
  432.   error = TT_New_Glyph (face, &glyph);
  433.   if (error) fatal_error ("couldn't create new glyph.");
  434.                                 /* Get the requested cmap. */
  435.   num_cmap = TT_Get_CharMap_Count (face);
  436.   for (cmapindex=0; cmapindex < num_cmap; cmapindex++) {
  437.     TT_Get_CharMap_ID (face, cmapindex, &platformID, &encodingID);
  438.     if (platformID == pid && encodingID == eid) break;
  439.   }
  440.   if (cmapindex == num_cmap) { 
  441.     mesg ("Possible platform and encoding ID pairs:");
  442.     for (cmapindex=0; cmapindex < num_cmap; cmapindex++) {
  443.       TT_Get_CharMap_ID (face, cmapindex, &platformID, &encodingID);
  444.       mesg ("  (%d, %d)", platformID, encodingID);
  445.     }
  446.     mesg ("\n");
  447.     fatal ("No character map for given platform %d encoding %d.", pid, eid);
  448.   }
  449.   /*  malloc for glyph data */
  450.   error = TT_Get_CharMap (face, cmapindex, &cmap);
  451.   if (error) fatal_error ("cannot load cmap.");
  452.   
  453.   return TRUE;
  454. }   
  455.  
  456. /* 
  457.  *  Load glyph's outline and metrics
  458.  */
  459. int
  460. LoadTrueTypeChar (int idx)
  461. {
  462.   TT_Matrix scale = {(1<<16)/64, 0, 0, (1<<16)/64};
  463.   error = TT_Load_Glyph (instance, glyph, idx, TTLOAD_DEFAULT);
  464.   if (error) fatal_error ("load glyph");
  465.   error = TT_Get_Glyph_Outline (glyph, &outline);
  466.   if (error) fatal_error ("get glyph outlines.");
  467.   TT_Transform_Outline (&outline, &scale);
  468.   error = TT_Get_Glyph_Metrics (glyph, &metrics);
  469.   if (error) fatal_error ("get glyph_metrics.");
  470.  
  471.   return TRUE;
  472. }
  473.  
  474. /*
  475.  *  Header of Type1 font.
  476.  */
  477. void 
  478. PS_Head(FILE *out, int plane, EncVec* planeEV, char* font, int UID) 
  479. {
  480.   EVcRange* cRange = planeEV->codeRange; 
  481.   UShort    numCR  = planeEV->numCodeRanges;
  482.   int       cjk = 0, nGlyph = 0, irange;
  483.   EVLow*    pLow = cRange->low;
  484.   UShort    nLow = cRange->numLowRanges;
  485.   int       ipl, ilow, ich;
  486.  
  487.  
  488.   fprintf(out, "%%!FontType1-1.0: CJK-%s 001.001\n",font);
  489.   fprintf(out, "%%%%Creator: %s ", prog);
  490.   fprintf(out, "%s %s\n", TTF2PFB_VERSION, rcsid);
  491.   Fputs("%%CreationDate: Feb 1st, 1998");
  492.   Fputs("%%VMusage: 030000 030000");
  493.   Fputs("11 dict begin");
  494.   Fputs("/FontInfo 8 dict dup begin");
  495.   Fputs("/version (001.001) readonly def");
  496.   if (compact)
  497.     fprintf(out, "/FullName (%s%02d) readonly def\n",font,plane);
  498.   else
  499.     fprintf(out, "/FullName (%s%02X) readonly def\n",font,plane);
  500.   fprintf(out, "/FamilyName (%s) readonly def\n",font);
  501.   Fputs("/Weight (Regular) readonly def");
  502.   Fputs("/ItalicAngle 0 def");
  503.   Fputs("/isFixedPitch false def");
  504.   /*  Fputs("/UnderlineThickness 50 def"); */
  505.   Fputs("end readonly def");
  506.   if (compact)
  507.     fprintf(out, "/FontName /%s%02d def\n",font,plane);
  508.   else
  509.     fprintf(out, "/FontName /%s%02X def\n",font,plane);
  510.   Fputs("/PaintType 0 def");
  511.   Fputs("/FontType 1 def");
  512.   if (fontShift == 0) 
  513.     Fputs("/FontMatrix [0.001 0 0 0.001 0 0] readonly def");
  514.   else
  515.     fprintf(out, "/FontMatrix [0.001 0 0 0.001 0 %5.3f] readonly def\n",
  516.             fontShift);
  517.   Fputs("/Encoding 256 array");
  518.   Fputs("0 1 255 {1 index exch /.notdef put} for");
  519.                                 /* encoding vector */
  520.   for (irange=0; irange<numCR; irange++, cRange++) {
  521.     pLow = cRange->low;
  522.     nLow = cRange->numLowRanges;
  523.     for (ipl=cRange->high.start; ipl<=cRange->high.end; ipl++) {
  524.       if (nLow == 0) {
  525.         nGlyph = 0x100;
  526.         for (ich=0; ich<=0xff; ich++)
  527.           fprintf(out, "dup %d /cjk%02X%02X put\n",ich,ipl,ich);
  528.       } else
  529.         for (ilow = 0; ilow < nLow; ilow++, pLow++) {
  530.           if (!compact) cjk = pLow->start;
  531.           nGlyph += pLow->end - pLow->start + 1;
  532.           for (ich=pLow->start; ich<=pLow->end; ich++, cjk++)
  533.             fprintf(out, "dup %d /cjk%02X%02X put\n",cjk,ipl,ich);
  534.         }
  535.     }
  536.   }
  537.  
  538.   Fputs("readonly def");
  539.   Fputs("/FontBBox [0 -300 1000 1000] readonly def");
  540.   fprintf(out, "/UniqueID %d%03d def\n",UID,plane);
  541.   Fputs("currentdict end");
  542.   Fputs("currentfile eexec");
  543.   Fputs("dup /Private 8 dict dup begin");
  544.   Fputs("/-| { string currentfile exch readstring pop } executeonly def");
  545.   Fputs("/|- { noaccess def } executeonly def");
  546.   Fputs("/| { noaccess put } executeonly def");
  547.   Fputs("/BlueValues [ ] |-");
  548.   Fputs("/ForceBold true def");
  549.   Fputs("/LanguageGroup 1 def");
  550.   Fputs("/RndStemUp false def");
  551.   Fputs("/MinFeature{16 16} |-");
  552.   Fputs("/password 5839 def");
  553.   fprintf(out, "/UniqueID %d%03d def\n",UID,plane);
  554.   Fputs("/Subrs 4 array");
  555.   Fputs("dup 0 { 3 0 callothersubr pop pop setcurrentpoint return } |");
  556.   Fputs("dup 1 { 0 1 callothersubr return } |");
  557.   Fputs("dup 2 { 0 2 callothersubr return } |");
  558.   Fputs("dup 3 { return } |");
  559.   Fputs("|-");
  560.   fprintf(out, "2 index /CharStrings %d dict dup begin\n", nGlyph+1);
  561. }
  562.  
  563. /*
  564.  * tail of Type1 font
  565.  */
  566. void
  567. PS_Tail (FILE *out)
  568. {
  569.   Fputs("/.notdef { 0 250 hsbw endchar } |-");
  570.   Fputs("end end readonly put noaccess put");
  571.   Fputs("dup /FontName get exch definefont pop");
  572.   Fputs("mark currentfile closefile");
  573. }
  574.  
  575. /*
  576.  *  use the rrcurveto command on more than one off points  
  577.  */
  578. void 
  579. PS_Curveto (FILE *out, TT_F26Dot6 x, TT_F26Dot6 y, int s, int e)
  580. {
  581.   int  N, i;
  582.   TT_F26Dot6 sx[3], sy[3], cx[4], cy[4];
  583.  
  584.   N = e-s+1;
  585.   cx[0] = lastpsx; cy[0] = lastpsy;
  586.   if (s == e) {
  587.     cx[1] = (2*outline.points[s].x+outline.points[s-1].x)/3;
  588.     cy[1] = (2*outline.points[s].y+outline.points[s-1].y)/3;
  589.     cx[2] = (2*outline.points[s].x+x)/3;
  590.     cy[2] = (2*outline.points[s].y+y)/3;
  591.     cx[3] = x;
  592.     cy[3] = y;
  593.     fprintf(out, "%d %d %d %d %d %d rrcurveto\n",
  594.             Coord(cx[1]-cx[0]),Coord(cy[1]-cy[0]),
  595.             Coord(cx[2]-cx[1]),Coord(cy[2]-cy[1]),
  596.             Coord(cx[3]-cx[2]),Coord(cy[3]-cy[2]));
  597.   } else {
  598.     for(i=0; i<N; i++) {
  599.       sx[0] = (i==0) ? outline.points[s-1].x :
  600.         (outline.points[i+s].x+outline.points[i+s-1].x)/2;
  601.       sy[0] = (i==0) ? outline.points[s-1].y :
  602.         (outline.points[i+s].y+outline.points[i+s-1].y)/2;
  603.       sx[1] = outline.points[s+i].x;
  604.       sy[1] = outline.points[s+i].y;
  605.       sx[2] = (i==N-1) ? x : (outline.points[s+i].x+outline.points[s+i+1].x)/2;
  606.       sy[2] = (i==N-1) ? y : (outline.points[s+i].y+outline.points[s+i+1].y)/2;
  607.       cx[1] = (2*sx[1]+sx[0])/3;
  608.       cy[1] = (2*sy[1]+sy[0])/3;
  609.       cx[2] = (2*sx[1]+sx[2])/3;
  610.       cy[2] = (2*sy[1]+sy[2])/3;
  611.       cx[3] = sx[2];
  612.       cy[3] = sy[2];
  613.       fprintf(out, "%d %d %d %d %d %d rrcurveto\n",
  614.               Coord(cx[1]-cx[0]),Coord(cy[1]-cy[0]),
  615.               Coord(cx[2]-cx[1]),Coord(cy[2]-cy[1]),
  616.               Coord(cx[3]-cx[2]),Coord(cy[3]-cy[2]));
  617.       cx[0] = cx[3]; cy[0] = cy[3];
  618.     }
  619.   }
  620.   PS_LastPt(x,y);
  621. }
  622.  
  623. #ifdef DEBUG
  624. int     debug_Char_Code = 0xFFFF;
  625. FILE*   tmpout;
  626. int     showlabel = FALSE;
  627. int     no_glyph  = FALSE;
  628. int     no_control= FALSE;
  629. #define Fputps(_msg_) fprintf(tmpout, "%s\n", _msg_)
  630.  
  631. void 
  632. tmp_out (FILE* tmpout)
  633. {
  634.   int i, j;
  635.   /* backup the line for easy coding this postscript program */
  636.   /*
  637.   fprintf(tmpout,"/llx %d.0 def /lly %d.0 def /urx %d.0 def /ury %d.0 def\n",
  638.           Coord(metrics.bbox.xMin/64), Coord(metrics.bbox.yMin/64),
  639.           Coord(metrics.bbox.xMax/64), Coord(metrics.bbox.yMax/64));
  640.   */
  641.  
  642.   Fputps("%!PS");
  643.   Fputps("%%% CharString debugging program.");
  644.   Fputps("%%% Generated by: ttf2pfb $Revision: 1.6 $");
  645.   Fputps("%%% plot char-string (pathes defined in /cjkxxxx)");
  646.   Fputps("");
  647.   Fputps("%%% user-defined parameter");
  648.   Fputps("/scalefactor .6 def");
  649.   Fputps("%% 0 black, 1 white");
  650.   Fputps("/glyph-outline-gray 0 def");
  651.   Fputps("/control-point-gray 0.7 def");
  652.   Fputps("");
  653.   Fputps("%%% calculate shifts and scale factor");
  654.   Fputps("currentpagedevice /PageSize get dup");
  655.   Fputps("0 get /pagewidth exch def");
  656.   Fputps("1 get /pageheight exch def");
  657.   Fputps("");
  658.   fprintf(tmpout,"/llx %d.0 def /lly %d.0 def /urx %d.0 def /ury %d.0 def\n",
  659.           Coord(metrics.bbox.xMin/64), Coord(metrics.bbox.yMin/64),
  660.           Coord(metrics.bbox.xMax/64), Coord(metrics.bbox.yMax/64));
  661.   Fputps("/olwidth urx llx sub def");
  662.   Fputps("/olheight ury lly sub def");
  663.   Fputps("");
  664.   Fputps("/scale scalefactor pagewidth mul olwidth div def");
  665.   Fputps("/xshift pagewidth 1 scalefactor sub mul 2 div def");
  666.   Fputps("/yshift pageheight olheight scale mul sub 2 div def");
  667.   Fputps("");
  668.   Fputps("%% save old gray-scale value");
  669.   Fputps("/oldgray currentgray def");
  670.   Fputps("");
  671.   Fputps("%%% for point sequence label");
  672.   Fputps("/TimesRoman 8 selectfont");
  673.   Fputps("/i++ {i /i i 1 add def} def");
  674.   Fputps("/itos {4 string cvs} def");
  675.   Fputps("/point {2 copy i++ 3 1 roll 5 3 roll} def");
  676.   Fputps("/drawlabel");
  677.   Fputps("  {{moveto dup 0 eq {exit}");
  678.   Fputps("    {itos show} ifelse} loop pop} def");
  679.   Fputps("/nodrawlabel {clear} def");
  680.   Fputps("/i 0 def");
  681.   Fputps("");
  682.   Fputps("%%% for drawing glyph paths, redefine commands used in CharString");
  683.   Fputps("%% scaled to proper size");
  684.   Fputps("/addr {scale mul 3 -1 roll add 3 1 roll");
  685.   Fputps("       scale mul add exch 2 copy} def");
  686.   if (no_glyph) {
  687.     Fputps("/rmoveto {addr pop pop point} def");
  688.     Fputps("/rlineto {addr pop pop point} def");
  689.     Fputps("/rrcurveto {8 4 roll addr 8 -2 roll addr 8 -2 roll addr");
  690.     Fputps("            8 2 roll 6 {pop} repeat point} def");
  691.   } else {
  692.     Fputps("/rmoveto {addr moveto point} def");
  693.     Fputps("/rlineto {addr lineto point} def");
  694.     Fputps("/rrcurveto {8 4 roll addr 8 -2 roll addr 8 -2 roll addr");
  695.     Fputps("            8 2 roll curveto point} def");
  696.   }
  697.   Fputps("/hsbw {pop pop");
  698.   Fputps("  xshift llx scale mul sub");
  699.   Fputps("  yshift lly scale mul sub} def");
  700.   Fputps("/endchar {stroke pop pop} def");
  701.   Fputps("");
  702.   Fputps("%%% for drawing control paths");
  703.   Fputps("/T {pop lly sub scale mul yshift add exch");
  704.   Fputps("        llx sub scale mul xshift add exch } def");
  705.   Fputps("/mt {T 2 copy moveto} def");
  706.   if (no_control) 
  707.     Fputps("/lt {T} def");
  708.   else
  709.     Fputps("/lt {T 2 copy lineto} def");
  710.   Fputps("");
  711.   Fputps("1 setlinecap 1 setlinejoin");
  712.   Fputps("%%% draw control points and paths");
  713.   Fputps("control-point-gray setgray");
  714.  
  715.   for (i = 0, j = 0; i < outline.n_contours; i++) {
  716.     fprintf (tmpout, "\n");
  717.     fprintf (tmpout, "%d %d %d %d mt\n", j, Coord(outline.points[j].x),
  718.              Coord(outline.points[j].y), outline.flags[j]);
  719.     j++;
  720.     for (; j <= outline.contours[i]; j++) 
  721.       fprintf (tmpout, "%d %d %d %d lt\n", j, Coord(outline.points[j].x),
  722.                Coord(outline.points[j].y), outline.flags[j]);
  723.     Fputps("closepath");
  724.   }
  725.   Fputps("stroke");
  726.   if (showlabel && !no_control)
  727.     Fputps("drawlabel");
  728.   else
  729.     Fputps("nodrawlabel");
  730.   Fputps("");
  731.   Fputps("%%% draw glyph outlines");
  732.   Fputps("glyph-outline-gray setgray");
  733.   Fputps("");
  734. }
  735. #endif
  736.  
  737. /*
  738.  * Construct CharString of a glyph
  739.  */
  740. short
  741. PS_CharString (FILE *out, UShort char_Code) 
  742. {
  743.   int    idx, i, j;
  744.   UShort start_offpt, end_offpt = 0, fst;
  745. #if DEBUG
  746.   FILE* oldout = out;
  747.   int   loop   = 1;
  748. #endif
  749.  
  750.   if (force_enc == X)
  751.     char_Code = JIS_to_SJIS (char_Code);
  752.  
  753.   idx = TT_Char_Index (cmap, char_Code);
  754.   if (idx == 0) {
  755.     fprintf(out, "/cjk%04X { 0 250 hsbw endchar } |-\n", char_Code);
  756.     return FALSE;
  757.   }
  758.  
  759.   if (!LoadTrueTypeChar(idx))
  760.     fatal ("couldn't load character: %d, code= %d", idx, char_Code);
  761.  
  762.   /* Begin string */
  763.   fprintf(out, "/cjk%04X {\n", char_Code);
  764.  
  765. #ifdef DEBUG
  766.   if (char_Code == debug_Char_Code) {
  767.     tmp_out(tmpout);
  768.     out  = tmpout;
  769.     loop = 0;
  770.   }
  771.   for (;loop<2;loop++) {
  772. #endif
  773.  
  774.   /*  coordinates are all relative to (0,0) in FreeType */
  775.   fprintf(out, "0 %d hsbw\n", (int)(metrics.advance/64));
  776.  
  777.   /* Initialize ending contour point, relative coordinates */
  778.   lastpsx = lastpsy = 0;
  779.  
  780.   for (i = 0, j = 0; i < outline.n_contours /*contours*/; i++) {
  781.     fst = j;
  782.     PS_Moveto (outline.points[j].x, outline.points[j].y);
  783.     j++;
  784.  
  785.     start_offpt = 0; /*start at least 1*/
  786.     /* data pts for all contours stored in one array.
  787.        each round j init at last j + 1 */
  788.  
  789.     /* start_offpt means start of off points.
  790.        0 means no off points in record.
  791.        N means the position of the off point.
  792.        end_offpt means the ending off point.
  793.        lastx, lasty is the last ON point from which Curve and Line
  794.        shall start.
  795.        */
  796.  
  797.     /* start with j=0. into loop, j=1.
  798.        if pt[1] off, if start_offpt == 0, toggle start_offpt
  799.        next j=2. if on, now start_off != 0, run Curveto.
  800.        if pt[1] on, start_off == 0, will run Lineto.
  801.        */
  802.     for (; j <= outline.contours[i]; j++) {
  803.       if (!(outline.flags[j] & TT_Flag_On_Curve)) {
  804.         if (!start_offpt) { start_offpt = end_offpt = j; }
  805.         else end_offpt++;
  806.       }
  807.       else {                    /*On Curve*/
  808.         if (start_offpt) {
  809.           /* start_offpt stuck at j, end_offpt++.
  810.              end_offpt - start_offpt gives no of off pts.
  811.              start_offpt gives start of sequence.
  812.              why need outline.xCoord[j] outline.yCoord[j]?
  813.              */
  814.           PS_Curveto(out, outline.points[j].x, outline.points[j].y,
  815.                      start_offpt, end_offpt);
  816.           start_offpt = 0;
  817.             
  818.           /* also use start_offpt as indicator to save one variable!! 
  819.              after curveto, reset condition. */
  820.         }
  821.         else PS_Lineto(outline.points[j].x, outline.points[j].y);
  822.       }
  823.     }
  824.     /* looks like closepath fst = first, i.e. go back to first */
  825.     if (start_offpt)
  826.       PS_Curveto(out, outline.points[fst].x, outline.points[fst].y,
  827.                  start_offpt, end_offpt);
  828.     else
  829.       Fputs("closepath"); 
  830.   }
  831.  
  832.   Fputs("endchar");
  833.  
  834. #if DEBUG
  835.     out = oldout;
  836.   }
  837.   if (char_Code == debug_Char_Code) {
  838.     if (showlabel && !no_glyph)
  839.       Fputps("drawlabel");
  840.     else
  841.       Fputps("nodrawlabel");
  842.     Fputps("");
  843.     Fputps("%%% end of drawing");
  844.     Fputps("oldgray setgray");
  845.     Fputps("showpage");
  846.     fclose(tmpout);
  847.   }
  848. #endif
  849.  
  850.   Fputs(" } |-");
  851.   return TRUE;
  852. }
  853.  
  854. /*
  855.  *  Get code ranges of an encoding scheme either from 
  856.  *  the eVecMap or an code range file.
  857.  */
  858. EncVec*
  859. Get_EncVec (FILE *enc)
  860. {
  861.   EncVec*    encVec = NULL;
  862.   EVcRange*  cRange = NULL;
  863.   EVLow*     lByte  = NULL;
  864.   UShort     numCR = 0, numLow = 0;
  865.   int        start, end;
  866.   int        buflen = LINELEN, numAssigned;
  867.   char       buf[LINELEN];
  868.  
  869.   if (force_enc != 0)
  870.     return eVecMap_force[force_enc];
  871.  
  872.   if (enc == NULL && eVecMap[pid][eid] != NULL)
  873.     return eVecMap[pid][eid];
  874.                                 /* parse each code range line */
  875.   while (fgets(buf, buflen, enc) != NULL) {
  876.     if (buf[0] != '#' && buf[0] != '\n') {
  877.       if (strrchr(buf,':') != NULL) {
  878.                                 /* if there is no high declared before low */
  879.         if (lByte != NULL) {
  880.           if (cRange == NULL) {
  881.                                 /* default code range '0x00-0x00:' */
  882.             cRange = re_alloc (cRange, ++numCR*sizeof(EVcRange), "Get_EncVec");
  883.             cRange->high.start = cRange->high.end = 0;
  884.           }
  885.                                 /* Assign the lastest low */
  886.           cRange->low = lByte;
  887.           cRange->numLowRanges = numLow;
  888.         }
  889.                                 /* New high byte range */
  890.         cRange = re_alloc (cRange, ++numCR*sizeof(EVcRange), "Get_EncVec");
  891.         (cRange+numCR-1)->numLowRanges = numLow = 0;
  892.         lByte = NULL;
  893.                                 /* Parse code range */
  894.         numAssigned = sscanf (buf, "%i %*40s %i", &start, &end);
  895.         if (numAssigned <= 0 || numAssigned > 2) {
  896.           mesg ("%s: Get_EncVec: wrong code range.\n", prog);
  897.           return NULL;
  898.         } else {
  899.           (cRange+numCR-1)->high.start = start;
  900.           if (numAssigned == 1)
  901.             (cRange+numCR-1)->high.end = start;
  902.           else
  903.             (cRange+numCR-1)->high.end = end;
  904.         }
  905.       } else {
  906.         lByte = re_alloc (lByte, ++numLow*sizeof(EVLow), "Get_EncVec");
  907.         numAssigned = sscanf (buf, "%i %*40s %i", &start, &end);
  908.         if (numAssigned <= 0 || numAssigned > 2) {
  909.           mesg ("%s: Get_EncVec: wrong code range.\n", prog);
  910.           return NULL;
  911.         } else {
  912.           (lByte+numLow-1)->start = start;
  913.           if (numAssigned == 1)
  914.             (lByte+numLow-1)->end = start;
  915.           else
  916.             (lByte+numLow-1)->end = end;
  917.         }
  918.       }
  919.     }
  920.   }
  921.   if (cRange == NULL) {
  922.     cRange = re_alloc (cRange, ++numCR*sizeof(EVcRange), "Get_EncVec");
  923.     cRange->high.start = cRange->high.end = 0;
  924.     cRange->numLowRanges = 0;
  925.   }
  926.   if (lByte != NULL) {
  927.     cRange->low = lByte;
  928.     cRange->numLowRanges = numLow;
  929.   }
  930.   encVec = re_alloc (encVec, 1*sizeof(EncVec), "Get_EncVec");
  931.   encVec->numCodeRanges = numCR;
  932.   encVec->codeRange = cRange;
  933.   return encVec;
  934. }
  935.  
  936. /*
  937.  *  Match code ranges by a font plane. 
  938.  */
  939.  
  940. EncVec*
  941. Get_PlaneEV (EncVec* encVec, int plane)
  942. {
  943.   UShort    numCR  = encVec->numCodeRanges;
  944.   EVcRange* cRange = encVec->codeRange;
  945.  
  946.   EncVec*   encV = NULL;
  947.   EVcRange* planeCR = NULL;
  948.   EVLow*    planeLow = NULL;
  949.   UShort    nCR = 0, nLow = 0;
  950.  
  951.   int       icr;
  952.  
  953.   if (compact) {
  954.     int iChar = 0;              /* summed # of chars */
  955.     int nChar = (plane-1) * 256; /* the first char code ranges recorded */
  956.     int recording = 0;
  957.                                 /* if compact, plane starts from 1 to be */
  958.                                 /* compatible to the CJK package */
  959.     if (plane < 1 || plane > 256) 
  960.       fatal ("Get_PlaneEV: given plane out of range.");
  961.  
  962.     for (icr = 0; icr < numCR; icr++, cRange++) {
  963.       UShort numLow = cRange->numLowRanges;
  964.       int    ipl;
  965.  
  966.       for (ipl=cRange->high.start; ipl<=cRange->high.end; ipl++) {
  967.         EVLow* pLow   = cRange->low;
  968.         int ilow;
  969.                                 
  970.         if (recording) {        /* if we have made a hit */
  971.           if (planeLow != NULL) { /* if low byte range has not been saved */
  972.             (planeCR+nCR-1)->low = planeLow;
  973.             (planeCR+nCR-1)->numLowRanges = nLow;
  974.             planeLow = NULL;
  975.           }
  976.                                 /* each new plane starts a EVcRange if */
  977.                                 /* iChar is still less than nChar */
  978.           if (iChar <= nChar) {
  979.             planeCR = re_alloc (planeCR, ++nCR*sizeof(EVcRange), "Get_PlaneEV");
  980.             (planeCR+nCR-1)->high.start = (planeCR+nCR-1)->high.end = ipl;
  981.             (planeCR+nCR-1)->numLowRanges = nLow = 0;
  982.           }
  983.         }
  984.                                 /* scan each low byte range */
  985.         for (ilow = 0; ilow < (numLow==0?1:numLow); ilow++, pLow++) {
  986.           int start, end, nLowChar;
  987.  
  988.           if (numLow == 0) {    /* default range */
  989.             start = 0x0;
  990.             end   = 0xff;
  991.           } else { 
  992.             start = pLow->start;
  993.             end   = pLow->end;
  994.           }
  995.           nLowChar = end - start + 1;
  996.           if (iChar+nLowChar > nChar) { /* a hit! */
  997.             int bchar = start + nChar - iChar;
  998.             if (planeCR == NULL) {  /* the first time code range is recorded */
  999.               planeCR = re_alloc (planeCR, ++nCR*sizeof(EVcRange), "Get_PlaneEV");
  1000.               (planeCR+nCR-1)->high.start = ipl;
  1001.               (planeCR+nCR-1)->high.end   = ipl;
  1002.             }
  1003.                                 /* adjust range boundary */
  1004.             if (recording==0)
  1005.               start = bchar;
  1006.             else 
  1007.               end = bchar; 
  1008.             nChar += 0xff;
  1009.                                 /* recording starts */
  1010.             recording++;
  1011.           }
  1012.           iChar += nLowChar;    /* next range */
  1013.  
  1014.           if (recording) {
  1015.                                 /* a new low range */
  1016.             if (iChar <= nChar) {
  1017.               planeLow = re_alloc (planeLow, ++nLow*sizeof(EVLow), "Get_PlaneEV");
  1018.               (planeLow+nLow-1)->start = start;
  1019.               (planeLow+nLow-1)->end   = end;
  1020.             }
  1021.             if (recording > 1 || iChar > nChar) { /* beyond recording range */
  1022.               (planeCR+nCR-1)->numLowRanges = nLow;
  1023.               (planeCR+nCR-1)->low = planeLow;
  1024.               encV = re_alloc (encV, 1*sizeof(EncVec), "Get_PlaneEV");
  1025.               encV->numCodeRanges = nCR;
  1026.               encV->codeRange = planeCR;
  1027.               return encV;
  1028.             }
  1029.           }
  1030.         }
  1031.       }
  1032.     }
  1033.   } else 
  1034.     for (icr = 0; icr < numCR; icr++, cRange++) {
  1035.       if (plane >= cRange->high.start && plane <= cRange->high.end) {
  1036.         encV = re_alloc (encV, 1*sizeof(EncVec), "Get_PlaneEV");
  1037.         planeCR = re_alloc (planeCR, 1*sizeof(EVcRange), "Get_PlaneEV");
  1038.  
  1039.         planeCR->high.start = planeCR->high.end = plane;
  1040.         planeCR->numLowRanges = cRange->numLowRanges;
  1041.         planeCR->low = cRange->low;
  1042.         encV->numCodeRanges = 1;
  1043.         encV->codeRange = planeCR;
  1044.         return encV;
  1045.       }
  1046.     }
  1047.   return NULL;
  1048. }
  1049.  
  1050. /*
  1051.  *  The main subroutine for generate Type1 font.
  1052.  *  One subfont per call.
  1053.  */
  1054. short
  1055. Generate_Fonts (FILE *out, int plane, FILE *enc, char *fname, int pfxUID)
  1056. {
  1057.   EncVec*    encVec = Get_EncVec (enc);
  1058.   EncVec*    planeEncVec;
  1059.   EVcRange*  cRange;
  1060.   UShort     numCR;
  1061.   UShort     code;
  1062.   int        ilow, iplan, ichar, irange;
  1063.   
  1064.   if (encVec == NULL)
  1065.     return FALSE;
  1066.   if ((planeEncVec = Get_PlaneEV (encVec, plane)) == NULL) {
  1067.     mesg ("%s: can't find encoding vector for the font plane 0x%X.\n",
  1068.          prog, plane);
  1069.     return FALSE;
  1070.   }
  1071.                                 /* Header of Type1 font */
  1072.   PS_Head (out, plane, planeEncVec, fname, pfxUID);
  1073.   
  1074.   numCR  = planeEncVec->numCodeRanges;
  1075.   cRange = planeEncVec->codeRange;
  1076.   for (irange=0; irange<numCR; irange++, cRange++) {
  1077.     EVLow* pLow = cRange->low;
  1078.     UShort nLow = cRange->numLowRanges;
  1079.     for (iplan=cRange->high.start; iplan<=cRange->high.end; iplan++) {
  1080.       if (nLow == 0) {
  1081.         for (ichar=0; ichar<=0xff; ichar++) {
  1082.           code = iplan<<8 | ichar;
  1083.           PS_CharString (out, code);
  1084.         }
  1085.       } else
  1086.         for (ilow = 0; ilow < nLow; ilow++, pLow++)
  1087.           for (ichar=pLow->start; ichar<=pLow->end; ichar++) {
  1088.             code = iplan<<8 | ichar;
  1089.             PS_CharString (out, code);
  1090.           }
  1091.     }
  1092.   }
  1093.   PS_Tail (out);
  1094.   
  1095.   return TRUE;
  1096. }
  1097.  
  1098. /*
  1099.  *  Main: process options, file I/O, etc.
  1100.  */
  1101. void
  1102. main(int argc, char *argv[])
  1103. {
  1104.   char  *infile, *outfile, *encFile, *fname = "UNKNOWN";
  1105.   FILE  *out, *enc;
  1106.   int   result, plane = 0, pfxUID = 7000;
  1107.    
  1108.   if ((prog = strrchr(argv[0], '/')))
  1109.     prog++;
  1110.   else
  1111.     prog = argv[0];
  1112.    
  1113.   /* setup encoding vectors of all I known */
  1114.   Known_Encodings ();
  1115.  
  1116.   out    = stdout;
  1117.   enc    = NULL;
  1118.   infile = outfile = encFile = NULL;
  1119.    
  1120.   argc--;
  1121.   argv++;
  1122.    
  1123.   while (argc > 0) {
  1124.     if (argv[0][0] == '-') {
  1125.       switch (argv[0][1]) {
  1126.       case 'v': case 'V':
  1127.         verbose = TRUE;
  1128.         break;
  1129.       case 'c': case 'C':
  1130.         compact = TRUE;
  1131.         break;
  1132.       case 'p': case 'P':
  1133.         result = argv[0][2];
  1134.         argc--;
  1135.         argv++;
  1136.         if (result == 'i' || result == 'I') {
  1137.           /* Set the platform ID. Assumed upper bound is 64 */
  1138.           if ((pid = atoi(argv[0])) < 0 || pid > 64) 
  1139.                                 /* Check the platform and encoding IDs. */
  1140.             fatal ("%s: invalid platform ID '%d'.\n", prog, pid);
  1141.         }
  1142.         else if (result == 'l' || result == 'L') {
  1143.           result = 0;
  1144.           while (argv[0][result] == '0' &&
  1145.                  toupper(argv[0][result+1]) != 'X')
  1146.             result++; /* no octal number */
  1147.           sscanf (&argv[0][result], "%i", &plane);
  1148.         }
  1149.         break;
  1150.       case 'e': case 'E':
  1151.                                 /* Set the encoding ID. */
  1152.         result = argv[0][2];
  1153.         argc--;
  1154.         argv++;
  1155.         if (result == 'i' || result == 'I') {
  1156.           if ((eid = atoi(argv[0])) < 0 || eid > 64) {
  1157.             fatal ("%s: invalid encoding ID '%d'.\n", prog, eid);
  1158.             exit (1);
  1159.           }}
  1160.         else if (result == 'n' || result == 'N')
  1161.           encFile = argv[0];
  1162.         break;
  1163.       case 'u': case 'U':
  1164.         argc--;
  1165.         argv++;
  1166.         pfxUID = atoi(argv[0]);
  1167.         break;
  1168.       case 'f': case 'F':
  1169.         result = argv[0][2];
  1170.         argc--;
  1171.         argv++;
  1172.         if (result == '\0')
  1173.           fname = argv[0];
  1174.         else if (result == 'o' || result == 'O') {
  1175.           switch (argv[0][0]) {
  1176.           case 'g': case 'G':
  1177.             force_enc = GB;
  1178.             break;
  1179.           case 'k': case 'K':
  1180.             force_enc = KS;
  1181.             break;
  1182.           case 'j': case 'J':
  1183.             force_enc = JIS;
  1184.             break;
  1185.           case 's': case 'S':
  1186.             force_enc = SJIS;
  1187.             break;
  1188.           case 'x': case 'X':
  1189.             force_enc = X;
  1190.           }
  1191.         }
  1192.         break;
  1193.       case 't': case 'T':
  1194.                                 /* Get the TTF file name. */
  1195.         argc--;
  1196.         argv++;
  1197.         infile = argv[0];
  1198.         break;
  1199.       case 'o': case 'O':
  1200.                                 /* Set the output file name. */
  1201.         argc--;
  1202.         argv++;
  1203.         outfile = argv[0];
  1204.         break;
  1205.       case 's': case 'S':       /* shift font bbox up or down */
  1206.         argc--; argv++;
  1207.         sscanf(argv[0], "%f", &fontShift); 
  1208.         break;
  1209. #ifdef DEBUG
  1210.       case 'd': case 'D':        /* character code for debuging */
  1211.         argc--; argv++;
  1212.         sscanf(argv[0], "%i", &debug_Char_Code); 
  1213.         tmpout = fopen("charstr-debug.ps", "wt");
  1214.         mesg ("You have specified the character code 0x%04x for debugging.\n",
  1215.               debug_Char_Code);
  1216.         mesg ("A PostScript program named charstr-debug.ps will be created.\n");
  1217.         break;
  1218.       case 'l': case 'L':
  1219.         showlabel = TRUE;
  1220.         break;
  1221.       case 'n': case 'N':
  1222.         result = argv[0][2];
  1223.         if (result == 'g' || result == 'G') 
  1224.           no_glyph = TRUE;
  1225.         else if (result == 'c' || result == 'C') 
  1226.           no_control = TRUE;
  1227.         break;
  1228. #endif
  1229.       default:
  1230.         Usage(1);
  1231.       }
  1232.     } else
  1233.                                 /* Set the input file name. */
  1234.       infile = argv[0];
  1235.  
  1236.     argc--;
  1237.     argv++;
  1238.   }
  1239.  
  1240.                                 /* Open the output file if specified. */
  1241.   if (outfile != NULL)
  1242.                                 /* Attempt to open the output file. */
  1243.     if ((out = fopen(outfile, "wt")) == 0) {
  1244.       fatal ("%s: unable to open the output file '%s'.\n",
  1245.               prog, outfile);
  1246.       exit(1);
  1247.     }
  1248.  
  1249.                                  /* Validate the values passed on the
  1250.                                    command line. */
  1251.   if (infile == NULL) {
  1252.     mesg ("%s: no input TTF file provided.\n", prog);
  1253.     Usage(1);
  1254.   }
  1255.  
  1256.   if (encFile != NULL) {
  1257.     if ((enc = fopen(encFile, "rt")) == 0) {
  1258.       fatal ("%s: no input code range file.\n", prog);
  1259.       exit (1);
  1260.     }
  1261.   }
  1262.                                 /* Initialize font engine */
  1263.   if (! Init_Font_Engine (infile)) {
  1264.     if (out != stdout) {
  1265.       fclose(out);
  1266.       (void) unlink(outfile);
  1267.     }
  1268.     exit (1);
  1269.   }
  1270.                                 /* Generate the disassembled PFB font
  1271.                                    from the TrueType font.  */
  1272.   if (Generate_Fonts (out, plane, enc, fname, pfxUID))
  1273.     result = 0;
  1274.   else
  1275.     result = 2;
  1276.  
  1277.   if (out != stdout) {
  1278.     fclose(out);
  1279.     if (result != 0) {
  1280.       mesg ("%s: An error occured when generating", prog);
  1281.       mesg (" the font, so delete the output file.\n");
  1282.       /* (void) unlink(outfile); */
  1283.     }
  1284.   }
  1285.  
  1286.   TT_Close_Face (face);
  1287.   TT_Done_FreeType (engine);
  1288.  
  1289.   exit(result);
  1290. }
  1291.  
  1292.  
  1293. /* end of ttf2pfb.c */
  1294.